package org.example.server.tcp;

import cn.hutool.core.util.IdUtil;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;
import lombok.extern.slf4j.Slf4j;
import org.example.RpcApp;
import org.example.constant.ProtocolConstant;
import org.example.enums.ProtocolMessageSerializerEnum;
import org.example.enums.ProtocolMessageTypeEnum;
import org.example.model.RpcRequest;
import org.example.model.RpcResponse;
import org.example.model.ServiceMetaInfo;
import org.example.protocol.ProtocolMessage;
import org.example.protocol.ProtocolMessageDecoder;
import org.example.protocol.ProtocolMessageEncoder;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

/**
 * @description TODO
 * @author sats@jz
 * @date 2025年01月11日 22:07
 */
@Slf4j
public class VertxTcpClient {

    public static RpcResponse doRequest(RpcRequest rpcRequest, ServiceMetaInfo serviceMetaInfo) throws Exception {
        // 发送TCP请求
        Vertx vertx = Vertx.vertx();
        NetClient client = vertx.createNetClient();
        CompletableFuture<RpcResponse> responseFuture = new CompletableFuture<>();
        client.connect(serviceMetaInfo.getServicePort(), serviceMetaInfo.getServiceHost(), res -> {
            if(!res.succeeded()){
                log.error("TCP client connect error");
                responseFuture.completeExceptionally(res.cause());
                return;
            }
            NetSocket socket = res.result();
            // 发送数据
            // 构造消息
            ProtocolMessage<RpcRequest> protocolMessage = new ProtocolMessage<>();
            ProtocolMessage.Header header = new ProtocolMessage.Header();
            header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
            header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
            header.setSerializer((byte) ProtocolMessageSerializerEnum.getEnumByValue(RpcApp.getRpcConfig().getSerializerName()).getKey());
            header.setMessageType((byte) ProtocolMessageTypeEnum.REQUEST.getKey());
            header.setRequestId(IdUtil.getSnowflakeNextId());
            protocolMessage.setHeader(header);
            protocolMessage.setBody(rpcRequest);

            try {
                Buffer encoderBuffer = ProtocolMessageEncoder.encoder(protocolMessage);
                socket.write(encoderBuffer);
            } catch (IOException e) {
                throw new RuntimeException("协议消息编码错误");
            }


            // 接受响应
            TcpBufferHandlerWrapper tcpBufferHandlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
                try {
                    ProtocolMessage<RpcResponse> decoderMessage = (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decoder(buffer);
                    responseFuture.complete(decoderMessage.getBody());
                } catch (IOException e) {
                    throw new RuntimeException("协议消息解码错误");
                }

            });

            socket.handler(tcpBufferHandlerWrapper);
        });
        RpcResponse rpcResponse = responseFuture.get();
        client.close();
        return rpcResponse;

    }
}
